iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 4
0
自我挑戰組

React初心者30天的探索之路系列 第 4

[Day 04] 理解React Virtual DOM

  • 分享至 

  • xImage
  •  

會特別寫這篇的原因是以前學習框架的時候只學語法而不懂原理,如果被問到使用框架有什麼好處可能也回答不太出來,由於React是透過Virtual DOM來提升網頁渲染的效率,所以今天要來探討Virtual DOM的運作原理,在了解Virtual DOM之前先來了解什麼是DOM吧!

DOM是什麼?

文件物件模型(Document Object Model, DOM)是 HTML、XML 和 SVG 文件的程式介面。它提供了一個文件(樹)的結構化表示法,並定義讓程式可以存取並改變文件架構、風格和內容的方法。(擷取MDN的部分說明

由下圖可以知道DOM是樹狀結構從document根結點向下延伸,下面依附了許多子節點

我們很常利用js來操作DOM,當瀏覽器在更新畫面的時候會觸發repaint(回流)以及reflow(重繪)這兩個更新機制

repaint

畫面元素更換樣式時候就觸發(background-color、color…)

reflow

更改畫面的佈局(結構排列)就會觸發(更改視窗大小,操作css屬性:position、width、height…)

頻繁操作DOM其實相當吃瀏覽器資源,導致效能低落,這就是為甚麼我們需要vitural DOM,要修改一個子節點就要重新繪製整個DOM 聽起來就很不智慧,所以就要借助Virtual DOM的演算法,就可以只更新需要異動的部分。

Virtual DOM的流程

  1. 初次使用setState()方法的時候,React會先複製一份dom的物件(即為Virtual DOM)
  2. 當React component的state改變時,會比對先前的Virtual DOM和當前的 Virtual DOM差異,稱之為diff運算
  3. Virtual DOM先用自己的演算法(diff)算出實際需要更新的部分,比對兩者差異之後,再去更動真實的DOM,有效減少渲染的次數 ,提高效能

這是一般的html結構

<div id="header">  
    <h1 class="title">Apple</h1>
    <p class="content">lemon</p> 
</div>

這是Virtual DOM的結構,是JavaScript模擬出來的物件, 會以以下的格式儲存起來

{
    tag: "div",
    props: {
        id: "header"
    },
    children: [
        {
            tag: "h1",
            props: { className: "title" },
            children: ["Apple"]
        }, {
            tag: "p",
            props: { className: "content" },
            children: ["lemon"]
        }
    ]
}
  • type: DOM標籤名稱
  • props:DOM屬性
  • children:DOM子元素

下方就用程式碼來稍微模擬一下Virtual DOM的執行過程

  1. createELement :先使用Virtual DOM提供的createELement方法來生成真實的DOM
var count = 0;    

var tree = render(count);               
var rootNode = createElement(tree);     
document.body.appendChild(rootNode);
  1. 當count變動時 Virtual DOM進行比對 再將差異patch到實際的DOM
count++
var newTree = render(count);
var patches = diff(tree, newTree);
rootNode = patch(rootNode, patches);
tree = newTree;

什麼是patch?

patch指的是在原有的DOM結構上做異動

###關於diff演算法

傳統的diff演算法複雜度為O(n³) 處理100個節點就要進行100萬次的比對,Virtual DOM的diff演算法為O(n) 與傳統的差異在於下幾點:

  1. Virtual DOM只會比較同一層級的節點
  2. 同一層的節點為了識別個別具有唯一的key,為了避免節點只是移動又被重新創建一次
  3. 如果發現節點不見了其子節點也會一併刪除,不會做進一步的比對

以往如果是手動操作,每操作一次就會更新一次dom,如果是透過react setState就會是將多個操作合併為一次的操作,避免頻繁更新頁面,因此開發者只要專注在資料邏輯上,畫面的更新機制全部交給React處理即可。

參考資料

MDN
diff-algorithm-implemented-reactjs


上一篇
[Day 03] create-react-app資料夾結構
下一篇
[Day 05] React JSX - html 和JavaScript的完美結合
系列文
React初心者30天的探索之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
ashramwen
iT邦新手 5 級 ‧ 2021-10-14 01:25:23

很好的文章,virtual dom 說明得很清楚,不過 repaint 和 reflow 的說明是不是誤植相反了? XD

謝謝你的提醒 已更正XD

0
janlin002
iT邦好手 1 級 ‧ 2022-08-26 11:53:21

感謝清楚的解說,讓我更了解Virtual dom

不過下方的 replaint 拼錯了,應該是 repaint
當瀏覽器在更新畫面的時候會觸發replaint(回流)以及reflow(重繪)這兩個更新機制

謝謝你的提醒
已修正!

我要留言

立即登入留言